<template>
  <div class="employees-container">
    <div class="app-container">
      <!-- 通用工具栏 -->
      <PageTools>
        <template #slot-left>
          <span>共有 {{ total }} 条记录</span>
        </template>
        <template #slot-right>
          <el-button
            type="danger"
            size="small"
            @click="uploadBtnFn"
          >导入excel</el-button>
          <el-button
            type="success"
            size="small"
            @click="exportBtnFn"
          >导出excel</el-button>
          <el-button
            type="primary"
            size="small"
            @click="addEmployeesBtnFn"
          >新增员工</el-button>
        </template>
      </PageTools>

      <!-- 员工列表 + 分页 -->
      <el-card style="margin-top: 10px;">
        <el-table
          border
          :data="employeesList"
          :highlight-current-row="true"
          :default-sort="{prop: 'workNumber'}"
        >
          <el-table-column
            label="序号"
            type="index"
          />
          <el-table-column
            label="姓名"
            prop="username"
          />
          <el-table-column
            label="头像"
            prop="staffPhoto"
          >
            <template v-slot="{row}">
              <image-holder
                :src="row.staffPhoto"
                class="staffPhoto"
              />
            </template>
          </el-table-column>
          <el-table-column
            label="手机号"
            prop="mobile"
          />
          <el-table-column
            label="工号"
            prop="workNumber"
            sortable
            :sort-method="workNumberSortFn"
          />
          <el-table-column
            label="聘用形式"
            prop="formOfEmployment"
            :formatter="formatter"
          />
          <el-table-column
            label="部门"
            prop="departmentName"
          />
          <el-table-column
            label="入职时间"
            prop="timeOfEntry"
            :formatter="timeFormatter"
          />
          <el-table-column label="操作">
            <template v-slot="{row}">
              <el-button
                type="text"
                size="small"
                @click="$router.push('/employees/detail?id='+ row.id +'&from='+ row.formOfEmployment)"
              >查看</el-button>
              <el-button
                type="text"
                size="small"
                @click="showAssignRoleDialog(row.id)"
              >分配角色</el-button>
              <el-button
                type="text"
                size="small"
              >删除</el-button>
            </template>
          </el-table-column>

        </el-table>
        <!-- 分页组件 -->
        <el-row
          type="flex"
          justify="center"
          align="middle"
          style="height: 60px"
        >
          <!-- 分页区域 -->
          <el-pagination
            :current-page="query.page"
            :page-sizes="[10, 15, 20, 25]"
            :page-size="query.size"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-row>
      </el-card>

      <!-- 新增员工弹框组件 -->
      <el-dialog
        :visible.sync="showDialog"
        @close="closeDialogFn"
      >
        <empForm
          ref="empForm"
          :show-dialog.sync="showDialog"
          :tree-data="treeData"
          @addEmployeesFn="addEmployeesFn"
        />
      </el-dialog>

      <!-- 上传文件 -->
      <upload-excel-component
        v-show="false"
        ref="uploadExcel"
        :on-success="handleSuccess"
        :before-upload="beforeUpload"
      />

      <!-- 员工-分配角色权限 - 弹窗 -->
      <el-dialog
        title="分配角色"
        :visible="showRoleDialog"
      >
        <!-- 设置角色组件 -->
        <assign-role-dialog
          ref="assignRoleDialog"
          :role-ids="roleIds"
          :show.sync="showRoleDialog"
          :role-list="roleList"
          @addRoleEV="addRoleFn"
        />
      </el-dialog>

    </div>
  </div>
</template>

<script>
import {
  addEmployeesAPI,
  getDepartmentsListAPI,
  getEmployeesListAPI,
  getRoleListAPI,
  importEmployeeAPI,
  getUserAPI,
  assignRolesAPI
} from '@/api'
import Employees from '@/api/constant'
import dayjs from 'dayjs'
import empForm from './components/empForm.vue'
import UploadExcelComponent from '@/components/UploadExcel'
import { formatExcelDate, transTree } from '@/utils'
import AssignRoleDialog from './components/assignRoleDialog.vue'

export default {
  name: 'Employees',
  components: {
    empForm,
    UploadExcelComponent,
    AssignRoleDialog
  },
  data() {
    return {
      userRelations: {
        序号: 'id',
        姓名: 'username',
        头像: 'staffPhoto',
        手机号: 'mobile',
        工号: 'workNumber',
        聘用形式: 'formOfEmployment',
        部门: 'departmentName',
        入职日期: 'timeOfEntry'
      },
      query: {
        page: 1, // 页码
        size: 10 // 每页条数
      },
      employeesList: [], // 员工列表
      total: 0, // 数据总条数
      hireType: Employees.hireType, // 聘用形式，枚举数组
      showDialog: false, // 添加员工组件的展示
      treeData: [], // 存储部门列表(树结构)
      showRoleDialog: false, // 控制分配角色弹窗
      roleList: [], // 角色列表
      roleIds: [], // 选中员工的角色
      userId: '' // 操作的员工
    }
  },
  created() {
    this.getEmployeesListFn() // 获取员工列表
    this.getDepartmentsListFn() // 获取部门列表
    this.getRoleListFn() // 获取角色列表
  },
  methods: {
    // 每页显示的条数发生改变时触发
    handleSizeChange(newSize) {
      this.query.size = newSize
      this.getEmployeesListFn() // 获取员工列表
    },

    // 当前页面发生改变时触发
    handleCurrentChange(newPage) {
      this.query.page = newPage
      this.getEmployeesListFn() // 获取员工列表
    },

    // 获取员工列表 -> 发送请求
    async getEmployeesListFn() {
      const res = await getEmployeesListAPI(this.query)
      if (!res.success) this.$message.error(res.message)
      this.employeesList = res.data.rows
      this.total = res.data.total
    },

    // 格式化表格的某一项
    formatter(row, column, cellValue, index) {
      // 用数组的 find 方法找到 id = 1 的元素，再取出它的 value
      const obj = Employees.hireType.find((item) => item.id === +cellValue)
      return obj ? obj.value : '未知'
    },

    // 工号 -> 排序方法
    workNumberSortFn(a, b) {
      return +a.workNumber - +b.workNumber
    },

    // 时间格式化
    timeFormatter(row) {
      return dayjs(row.timeOfEntry).format('YYYY-MM-DD')
    },

    // 新增员工 -> 点击出弹窗
    addEmployeesBtnFn() {
      this.showDialog = true
    },

    // 弹窗 -> 关闭的回调
    closeDialogFn() {
      this.$refs.empForm?.$refs?.addForm?.resetFields()
    },

    // 获取部门列表 -> 发送请求
    async getDepartmentsListFn() {
      const res = await getDepartmentsListAPI()
      if (!res.success) return this.$message.error(res.message)
      this.treeData = transTree(res.data.depts, '')
    },

    // 新增员工 -> 发送请求
    async addEmployeesFn() {
      const res = await addEmployeesAPI({ ...this.$refs.empForm.formData })
      if (!res.success) this.$message.error(res.message)
      this.$message.success(res.message)
    },

    // 导入excel 按钮 -> 点击事件 -> 显示文件选择框
    uploadBtnFn() {
      this.$refs.uploadExcel.$refs['excel-upload-input'].click()
    },

    // 在上传 excel 文件后，做一个大小的判断
    beforeUpload(file) {
      const isLt1M = file.size / 1024 / 1024 < 1

      if (isLt1M) {
        return true
      }

      this.$message({
        message: 'Please do not upload files larger than 1m in size.',
        type: 'warning'
      })
      return false
    },

    // 接收 UploadExcel 组件内，读取表格成功的头部数据和表格题数据
    async handleSuccess({ results, header }) {
      // 处理数据
      const newResults = results.map((obj) => {
        const newObj = {}
        const keyArr = Object.keys(obj)
        keyArr.forEach((zhKey) => {
          if (zhKey === '入职时间' || zhKey === '转正日期') {
            newObj[this.userRelations[zhKey]] = formatExcelDate(obj[zhKey])
          } else newObj[this.userRelations[zhKey]] = obj[zhKey]
        })
        return newObj
      })

      const res = await importEmployeeAPI(newResults)
      if (!res.success) return this.$message.error(res.message)
      this.$message.success('操作成功')
    },

    // 导出excel 按钮 -> 点击事件 -> 自动下载excel文件
    async exportBtnFn() {
      const allEmployeesList = (
        await getEmployeesListAPI({
          page: 1,
          size: this.total
        })
      ).data.rows

      import('@/vendor/Export2Excel').then((excel) => {
        const keyArr = Object.keys(this.userRelations)
        const data = allEmployeesList.map((enObj, index) => {
          const newArr = []
          keyArr.forEach((zhKey) => {
            if (zhKey === '序号') newArr.push(index + 1)
            else if (zhKey === '聘用形式') {
              newArr.push(
                Employees.hireType.find(
                  (item) => item.id === +enObj[this.userRelations[zhKey]]
                )?.value || '未知'
              )
            } else newArr.push(enObj[this.userRelations[zhKey]])
          })
          return newArr
        })

        // @/vendor/Export2Excel 文件内封装的导出excel文件的方法
        excel.export_json_to_excel({
          header: keyArr,
          data,
          filename: 'excel-list', // 文件名称
          autoWidth: true, // 单元格宽度是否自适应
          bookType: 'xlsx' // 生成的文件类型
        })
      })
    },

    // 获取角色列表 -> 发送请求
    async getRoleListFn() {
      this.roleList = (
        await getRoleListAPI({
          page: 1,
          pagesize: (
            await getRoleListAPI({
              page: 1,
              pagesize: 10
            })
          ).data.total
        })
      ).data.rows
    },

    // 获取员工详情数据 -> 发送请求
    async showAssignRoleDialog(id) {
      this.userId = id
      this.showRoleDialog = true

      const infoRes = await getUserAPI(id)
      if (!infoRes.success) return this.$message.error(infoRes.message)

      this.$nextTick(() => {
        this.$refs.assignRoleDialog.roleIdList = infoRes.data.roleIds
      })
    },

    // 给员工分配角色 -> 发送请求
    async addRoleFn(roleIdList) {
      const res = await assignRolesAPI({ id: this.userId, roleIds: roleIdList })

      // 员工分配成功，给用户提示
      this.$message.success(res.message)
      // 关闭弹框
      this.showRoleDialog = false
      // 重新获取当前当前列表数据
      this.getEmployeesListFn()
    }
  }
}
</script>

<style lang="scss" scoped>
.staffPhoto {
  width: 100px;
  height: 100px;
  border-radius: 50%;
}
// ::v-deep 深度作用选择器
::v-deep .el-dialog__headerbtn {
  top: 10px;
}
</style>
